-------------------------------------------------------------------------------
---! 正在匹配的队列 多个房间
---! {room_id:room_ob}
local match_queue = {}
local match_running = true --匹配功能开启中
local new_room_id = 1000 --起始id

---! 匹配队列房间的最大人数
local max_match_number = 8

---! 平均匹配时间(s) {avg,all,num}
local avg_match_time = {0, 0, 0}

---! 平均匹配时间
register_post_init(
    function()
        THREAD_D:create(
            function()
                avg_match_time = CONFIG_D:read_match_time()
                ---! 每1小时保存平均匹配时间
                TIMER_D:start_timer(
                    3600,
                    function()
                        CONFIG_D:write_match_time(avg_match_time)
                    end
                )
            end
        )
    end
)

---! 获取玩家所在queue(即:room)
local function get_queue(user_ob)
    return user_ob:get_room()
end

---! 推送匹配信息
local function send_S2CMatchInfo(room_ob)
    local result = {}
    result.num = room_ob:get_user_num()
    room_ob:brocast_packet("tanker.S2CMatchInfo", result)
end

local function send_S2CQuitMatch(user_ob, status)
    local result = {}
    result.status = status
    user_ob:send_packet("tanker.S2CQuitMatch", result)
    spdlog.debug("match", "S2CQuitMatch user_id: %d status: %s", user_ob:get_id(), status)
end

---! 返回匹配信息
local function send_S2CEnterMatch(user_ob, room_ob, status)
    local result = {}
    result.status = status
    if status == 1 and room_ob then --已经在匹配中
        result.need_time = avg_match_time[1]
        result.need_num = max_match_number --最大人数
        result.begin_time = os.time() - user_ob:get_join_time()
        result.num = room_ob:get_user_num()
    end
    user_ob:send_packet("tanker.S2CEnterMatch", result)
end

local function send_S2CEnterMatch_team(user_obs, room_ob, status)
    local result = {}
    result.status = status
    if status == 1 and room_ob then --已经在匹配中
        result.need_time = avg_match_time[1]
        result.need_num = max_match_number --最大人数
        result.num = room_ob:get_user_num()

        local now_time = os.time()
        for _, user_ob in ipairs(user_obs) do
            if not user_ob:is_robot() then
                result.begin_time = now_time - user_ob:get_join_time()
                user_ob:send_packet("tanker.S2CEnterMatch", result)
            end
        end
    end
end
-------------------------------------------------------------------------------
---! 对外接口
-------------------------------------------------------------------------------
MATCH_D = {}

---! 从队列中查找最有可能匹配成功的房间
function MATCH_D:get_good_queue(num)
    local min_num
    local good_room
    for _, room_ob in pairs(match_queue) do
        local need = max_match_number - room_ob:get_user_num() --剩余需要人数
        if need == num then --人数刚好足够
            good_room = room_ob
            break
        end

        if not min_num or need < min_num then
            min_num = need
            good_room = room_ob
        end
    end
    return good_room
end

---! 关闭匹配系统
function MATCH_D:C2SMatchStop()
    match_running = false
end

---! 开启匹配系统
function MATCH_D:C2SMatchOpen()
    match_running = true
end

---! 进入匹配队列
function MATCH_D:C2SEnterMatch(user_ob)
    if not match_running then
        send_S2CEnterMatch(user_ob, nil, -1)
        return
    end

    ---! 是否已经在队列中
    local room_ob = user_ob:get_room()
    if room_ob then
        spdlog.debug("match", "C2SEnterMatch exists room_id %d", room_ob:get_id())
        send_S2CEnterMatch(user_ob, room_ob, 1)
        return
    end

    ---! 战斗中 则不匹配
    local combat_ob = user_ob:get_combat()
    if combat_ob then
         spdlog.debug("match", "C2SEnterMatch exists  combat_id %d", combat_ob:get_id())
        send_S2CEnterMatch(user_ob, nil, 3)
        return
    end

    -- 判断是否是组队玩家，并获取加入匹配的玩家列表
    local new_users
    local team = TEAM_D:get_team(user_ob)
    if team then
        -- 队长才可以匹配
        if user_ob:get_id() ~= team:get_captain() then
            send_S2CEnterMatch(user_ob, nil, 2)
            return
        end
        --匹配中就算
        team:set_fighting(true)
        new_users = team:get_user_obs()
    else
        -- 不是组队玩家,查找一个最优的房间
        new_users = {user_ob}
    end

    -- 查找一个最优的房间，没有房间则新建立一个
    local good_room = MATCH_D:get_good_queue(#new_users)
    if not good_room then
        good_room = ROOM_OB:create()
        new_room_id = new_room_id + 1
        good_room:set_id(new_room_id)
        match_queue[new_room_id] = good_room
    end

    if good_room:get_user_num() <= 0 then
        ---! 复用房间对象
        good_room:set_begin_time(os.time())
    end

    ---! 加入匹配队列
    MATCH_D:join_match(good_room, new_users)
end

---! 退出匹配队列
function MATCH_D:C2SQuitMatch(user_ob)
    local status = 1
    --如果有战斗 则不能退出匹配
    if user_ob:is_in_combat() then
        status = 3
    else
        --退出匹配
        if not self:quit_match(user_ob) then
            status = 2
        end
    end

    send_S2CQuitMatch(user_ob,status)
end

---! 加入匹配队列
function MATCH_D:join_match(room_ob, user_obs)
    --房间中加入当前队伍或单个玩家
    for _, user_ob in ipairs(user_obs) do
        room_ob:add_user(user_ob)
        spdlog.debug("match", "C2SEnterMatch user_id: %d match room_id %d", user_ob:get_id(), room_ob:get_id())
    end

    --返回匹配信息
    send_S2CEnterMatch_team(user_obs, room_ob, 1)

    --推送数量给所有玩家
    send_S2CMatchInfo(room_ob)

    --如果匹配满了,则可以进入游戏
    if room_ob:get_user_num() >= max_match_number then
        spdlog.debug("match", "C2SEnterMatch room_id %d loading_combat", room_ob:get_id())

        -- 战斗开始 移入到战斗队列中
        COMBAT_D:loading_combat(room_ob)

        --计算平均匹配时间
        local now = os.time()
        avg_match_time[3] = avg_match_time[3] + 1 --总匹配场数
        avg_match_time[2] = avg_match_time[2] + now - room_ob:get_begin_time() --总时间
        avg_match_time[1] = avg_match_time[2] // avg_match_time[3]

        -- 清理房间数据
        room_ob:clear_room()

        --[[ 房间对象清理，可供下次复用
        -- 删除满的队列
        match_queue[room_ob:get_id()] = nil --刪除
        --]]
    end
end

---! 玩家退出匹配,比如主动退出,掉线
function MATCH_D:quit_match(user_ob)
    ---! 是否已经在队列中
    local room_ob = user_ob:get_room()
    if room_ob then
        --如果在队伍中,则整个队伍都退出匹配
        local team = TEAM_D:get_team(user_ob)
        if team then
            local ids = team:get_user_ids()
            for _, id in ipairs(ids) do
                room_ob:del_user(id)
                local ob = USER_D:find_user(id)
                if ob then
                    send_S2CQuitMatch(ob, 1)
                end
            end
            team:set_fighting(false)
        else
            room_ob:del_user(user_ob:get_id())
        end

        if room_ob:get_user_num(true) > 0 then
            -- 推送数量给其它玩家
            send_S2CMatchInfo(room_ob)
        else
            -- 清理房间数据
            room_ob:clear_room()
        end
        return true
    end
    return false
end

---! 获取当前正在匹配的房间
function MATCH_D:get_match_queue()
    return match_queue
end

-------------------------------------------------------------------------------
---! 后台接口
-------------------------------------------------------------------------------

---! 修改匹配最大人数
function MATCH_D:set_match_number(num)
    max_match_number = num
    return max_match_number
end
